package iamutkarshtiwari.github.io.ananas.editimage.view;

import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.render.*;
import ohos.agp.utils.Color;
import ohos.app.Context;
import ohos.media.image.PixelMap;
import ohos.media.image.common.PixelFormat;
import ohos.media.image.common.Size;
import ohos.multimodalinput.event.TouchEvent;

public class CustomPaintView extends Component implements Component.EstimateSizeListener, Component.DrawTask, Component.TouchEventListener {
    private static final String TAG = CustomPaintView.class.getSimpleName();

    private Paint mPaint;
    private PixelMap mDrawBit;
    private Paint mEraserPaint;

    private Canvas mPaintCanvas = null;

    private float last_x;
    private float last_y;
    private boolean isEraser = false;

    private Color mColor;

    /**
     * 构造
     * @param context Context对象
     */
    public CustomPaintView(Context context) {
        super(context);
        init(context);
    }

    /**
     * 构造
     * @param context Context对象
     * @param attrSet AttrSet对象
     */
    public CustomPaintView(Context context, AttrSet attrSet) {
        super(context, attrSet);
        init(context);
    }

    /**
     * 构造
     * @param context Context对象
     * @param attrSet AttrSet对象
     * @param styleName 风格
     */
    public CustomPaintView(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
        init(context);
    }

    @Override
    //onMeasure
    public boolean onEstimateSize(int widthMeasureSpec, int heightMeasureSpec) {
//        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int width = EstimateSpec.getSize(widthMeasureSpec);
        int height = EstimateSpec.getSize(heightMeasureSpec);

        setEstimatedSize(
                EstimateSpec.getChildSizeWithMode(width, width, EstimateSpec.NOT_EXCEED),
                EstimateSpec.getChildSizeWithMode(height, height, EstimateSpec.NOT_EXCEED)
        );

        if (mDrawBit == null) {
            generatorBit();
        }

        return true;
    }

    private void generatorBit() {

        if (0 == getEstimatedWidth() || 0 == getEstimatedHeight()) return;

        PixelMap.InitializationOptions options = new PixelMap.InitializationOptions();
        options.pixelFormat = PixelFormat.ARGB_8888;
        options.size = new Size(getEstimatedWidth(), getEstimatedHeight());

        mDrawBit = PixelMap.create(options);
        mPaintCanvas = new Canvas(new Texture(mDrawBit));
    }

    private void init(Context context) {
        mPaint = new Paint();
        mPaint.setAntiAlias(true);

        mPaint.setColor(Color.RED);
        mPaint.setStrokeJoin(Paint.Join.ROUND_JOIN
        );
        mPaint.setStrokeCap(Paint.StrokeCap.ROUND_CAP);

        mEraserPaint = new Paint();
        mEraserPaint.setAlpha(0);
//        mEraserPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
        mEraserPaint.setBlendMode(BlendMode.CLEAR);
        mEraserPaint.setColorFilter(new ColorFilter(Color.TRANSPARENT.getValue(), BlendMode.CLEAR));
        mEraserPaint.setAntiAlias(true);
        mEraserPaint.setDither(true);
        mEraserPaint.setStyle(Paint.Style.STROKE_STYLE);
        mEraserPaint.setStrokeJoin(Paint.Join.ROUND_JOIN);
        mEraserPaint.setStrokeCap(Paint.StrokeCap.ROUND_CAP);
        mEraserPaint.setStrokeWidth(40);


        addDrawTask(this);
        setTouchEventListener(this);
        setEstimateSizeListener(this);
    }

    /**
     * 设置画笔粗细
     * @param color  颜色
     */
    public void setColor(Color color) {
        this.mColor = color;
        this.mPaint.setColor(mColor);
    }

    /**
     * 设置画笔粗细
     * @param width  数值
     */
    public void setWidth(float width) {
        this.mPaint.setStrokeWidth(width);
    }

    /**
     * 设置画笔透明度
     * 0.0-> 1.0
     * @param alpha 数值
     */
    public void setStrokeAlpha(float alpha) {
        this.mPaint.setAlpha(alpha);
    }

    @Override
    public void addDrawTask(DrawTask task) {
        super.addDrawTask(task);
        task.onDraw(this, mCanvasForTaskOverContent);
    }

    @Override
    public void onDraw(Component component, Canvas canvas) {
        if (mDrawBit != null) {
            canvas.drawPixelMapHolder(new PixelMapHolder(mDrawBit), 0, 0, new Paint());
        }
    }

    @Override
    public boolean onTouchEvent(Component component, TouchEvent event) {
        if (null == mPaintCanvas) {
            generatorBit();
        }

        boolean ret = true;    //super.onTouchEvent(event);
        int[] location = getLocationOnScreen();     //获取组件在屏幕的绝对位置
        float positionX = (float) ((double)event.getPointerScreenPosition(event.getIndex()).getX() - location[0]);
        float positionY = (float) ((double)event.getPointerScreenPosition(event.getIndex()).getY() - location[1]);

        switch (event.getAction()) {
            case TouchEvent.PRIMARY_POINT_DOWN:
                ret = true;
                last_x = positionX;
                last_y = positionY;
                break;
            case TouchEvent.POINT_MOVE:
                ret = true;
                mPaintCanvas.drawLine(last_x, last_y, positionX, positionY, isEraser ? mEraserPaint : mPaint);
                last_x = positionX;
                last_y = positionY;
                getContext().getUITaskDispatcher().asyncDispatch(this::invalidate);//this.postInvalidate();
                break;
            case TouchEvent.CANCEL:
            case TouchEvent.PRIMARY_POINT_UP:
                ret = false;
                break;
        }
        return ret;
    }

    /**
     * 设置是否为橡皮
     * @param eraser 是否是橡皮
     */
    public void setEraser(boolean eraser) {
        this.isEraser = eraser;
        mPaint.setColor(eraser ? Color.TRANSPARENT : mColor);
    }

    /**
     * 设置画笔粗细
     * @param width  数值
     */
    public void setEraserStrokeWidth(float width) {
        mEraserPaint.setStrokeWidth(width);
    }

    /**
     * 获取绘制的图像
     * @return 绘制的图像
     */
    public PixelMap getPaintBit() {
        return mDrawBit;
    }

    /**
     * 重置
     */
    public void reset() {
        if (mDrawBit != null && !mDrawBit.isReleased()) {
            mDrawBit.release();
        }

        generatorBit();
        this.invalidate();
    }
}
